package com.ilxqx.generator.core;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ilxqx.generator.parser.Rules;
import com.ilxqx.generator.parser.Table;
import com.ilxqx.generator.parser.TableField;
import com.ilxqx.generator.parser.impl.RulesImpl;
import com.ilxqx.generator.parser.impl.TableImpl;
import com.ilxqx.generator.po.RawTable;
import com.ilxqx.generator.po.RawTableField;
import com.ilxqx.generator.po.RawTableKey;
import com.ilxqx.generator.po.Rule;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Assert;

import java.util.List;
import java.util.Map;

/**
 * @author venus
 */
@Slf4j
public abstract class AbstractTableInfoParser implements TableInfoParser {

    /**
     * 解析表字段信息
     * @param rawTableFields 原始表字段信息
     * @return 表字段List
     */
    protected abstract List<TableField> parseTableFieldsInfo(List<RawTableField> rawTableFields);

    /**
     * 解析表键信息
     * @param rawTableKeys 原始键信息
     * @param tableFields 表字段信息
     */
    protected abstract void parseTableKeysInfo(List<RawTableKey> rawTableKeys, List<TableField> tableFields);

    /**
     * 解析字段注释规则
     *
     * @param comment 字段注释
     * @return 注释规则
     */
    protected Rules parseCommentRules(String comment) {
        String ruleString = StringUtils.substringBetween(comment, "[", "]");
        List<Rule> ruleList = Lists.newArrayList();
        String[] rules = StringUtils.split(ruleString, ",");
        if (rules != null) {
            for (String rule : rules) {
                // 跳过空的规则定义
                if (StringUtils.isBlank(rule)) {
                    continue;
                }
                String[] parts = StringUtils.split(rule, ":");
                Assert.isTrue(parts.length <= 2, "规则参数格式有误[" + rule + "]");
                if (parts.length == 2) {
                    // 有参数
                    String[] params = StringUtils.split(parts[1], "&");
                    Map<String, String> paramMap = Maps.newHashMap();
                    for (String param : params) {
                        if (StringUtils.isBlank(param)) {
                            continue;
                        }
                        String[] paramParts = StringUtils.split(param, "=");
                        Assert.isTrue(paramParts.length == 2, "规则参数格式有误[" + param + "]");
                        paramMap.put(paramParts[0], paramParts[1]);
                    }
                    // 构造对象
                    ruleList.add(new Rule(parts[0], paramMap));
                } else {
                    // 无参数
                    ruleList.add(new Rule(parts[0], Maps.newHashMapWithExpectedSize(2)));
                }
            }
        }

        return new RulesImpl(ruleList);
    }

    /**
     * 解析表信息
     *
     * @param rawTable 原生表信息
     * @return 表对象
     */
    @Override
    public Table parseTableInfo(RawTable rawTable) {
        TableImpl table = new TableImpl();
        log.info("解析表【{}】字段加工信息", rawTable.getTableName());
        List<TableField> tableFields = this.parseTableFieldsInfo(rawTable.getRawTableFields());
        log.info("解析表【{}】约束键加工信息", rawTable.getTableName());
        this.parseTableKeysInfo(rawTable.getRawTableKeys(), tableFields);
        table.setTableName(rawTable.getTableName());
        table.setTableComment(StringUtils.substringBefore(rawTable.getTableComment(), "["));
        table.setTableFields(tableFields);
        log.info("解析表【{}】注释规则", rawTable.getTableName());
        table.setTableRules(this.parseCommentRules(rawTable.getTableComment()));
        return table;
    }

}
